package com.jinzhi.jzweb.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.jinzhi.common.base.CoreServiceImpl;
import com.jinzhi.common.constants.MessagesEnum;
import com.jinzhi.common.utils.Result;
import com.jinzhi.common.utils.ShiroUtils;
import com.jinzhi.common.utils.StringUtil;
import com.jinzhi.jzapi.domain.UserDO;
import com.jinzhi.jzapi.utils.JWTUtil;
import com.jinzhi.jzweb.dao.JazUserHouseDao;
import com.jinzhi.jzweb.domain.*;
import com.jinzhi.jzweb.domain.param.UserHouseQuery;
import com.jinzhi.jzweb.service.*;
import com.jinzhi.sys.dao.UserDao;
import com.jinzhi.sys.service.UserRoleService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

import static jodd.datetime.JDateTimeDefault.formatter;


/***
 * @author ChangPanYuan
 * @Date 2024/5/10
 * @Description: 用户住宿
 * @Version 1.0
 */
@Service
public class JazUserHouseServiceImpl extends CoreServiceImpl<JazUserHouseDao, JazUserHouseDO> implements JazUserHouseService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private JazSysProjectService jazSysProjectService;

    @Autowired
    private JazUserAuntService jazUserAuntService;

    @Autowired
    private JazMessageService jazMessageService;

    @Autowired
    private JazBedNumberService jazBedNumberService;

    @Autowired
    private JazHouseTypesService jazHouseTypesService;
    @Autowired
    private UserRoleService userRoleService;


    /**
     * 定时器待开始的订单到时间了状态改为进行这种
     */
//    @Transactional
//    @Scheduled(cron = "0 0 0/3 * * ? ")//每隔三小时执行一次//cron = "0 0 0/3 * * ? "//fixedRate= 3000//3000毫秒刷新一次
//    @Scheduled(cron = "0 0/5 * * * ? ")//每隔5分钟执行一次//cron = "0 0/30 * * * ? "//fixedRate= 3000//3000毫秒刷新一次
//    public void updateUserHouse() {
//        //查询出开始时间已到的订单
//        EntityWrapper<JazUserHouseDO>   Wrapper = new EntityWrapper<>();
//        System.out.println("3小时执行一次这个定时任务");
//        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 定义日期格式
//        List<JazUserHouseDO> list = this.selectList(Wrapper);
//        //更改订单已经到时间的订单状态
//        for (int i=0; i < list.size();i++){
//            JazUserHouseDO jazUserHouseDO = new JazUserHouseDO();
//            jazUserHouseDO.setId(list.get(i).getId());
//            JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(list.get(i).getBedNumberId());
//            if (!StringUtils.isEmpty(list.get(i).getLeaveTime())){
//                Date parse = null;
//                try {
//                    parse = dateFormat.parse(list.get(i).getLeaveTime());
//                } catch (ParseException e) {
//                    throw new RuntimeException(e);
//                }
//                if (parse.before(new Date())||parse.equals(new Date())){
//                    //更改状态为已离开
//                    jazUserHouseDO.setStatus(2);
//                    this.updateById(jazUserHouseDO);
//                    System.out.println("更改住宿状态");
//                    //释放床号
//                    jazBedNumberDO.setIsOccupied(1);
//                    jazBedNumberService.updateById(jazBedNumberDO);
//                    System.out.println("更改床号状态");
//                }
//            }
//            JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO.getHouseTypeId());
//            List<JazBedNumberDO> list1 = jazBedNumberService.selectList(new EntityWrapper<JazBedNumberDO>().eq("house_type_id", jazHouseTypesDO.getId()));
//            List<JazBedNumberDO> collect = list1.stream().filter(e -> e.getIsOccupied().equals(0)).collect(Collectors.toList());
//            jazHouseTypesDO.setStay(collect.size());
//            if (Objects.equals(jazHouseTypesDO.getCanStay(), jazHouseTypesDO.getStay())){
//                jazHouseTypesDO.setStatus(2);
//            }else if (jazHouseTypesDO.getStay()==null|| jazHouseTypesDO.getStay()==0){
//                jazHouseTypesDO.setStatus(0);
//            }else if (jazHouseTypesDO.getCanStay()>jazHouseTypesDO.getStay()){
//                jazHouseTypesDO.setStatus(1);
//            }
//            jazHouseTypesService.updateById(jazHouseTypesDO);
//            System.out.println("更改房型已住数量");
//        }
//
//    }

    /**
     * 分页查询住宿列表
     *
     * @param userHouseQuery
     * @return
     */
    @Override
    public Page<JazUserHouseDO> getUserHousePage(UserHouseQuery userHouseQuery) {
        Page<JazUserHouseDO> page = new Page<>(
                Optional.of(userHouseQuery.getCurr()).orElse(1),
                Optional.of(userHouseQuery.getPageSize()).orElse(10));
        Wrapper wrapper  = new EntityWrapper().
                like(StringUtil.notEmpty(userHouseQuery.getUsername()),"username",userHouseQuery.getUsername()).
                like(StringUtil.notEmpty(userHouseQuery.getMobile()),"phone",userHouseQuery.getMobile()).
                like(StringUtil.notEmpty(userHouseQuery.getCommunityName()),"community_name",userHouseQuery.getCommunityName()).
                eq(Objects.nonNull(userHouseQuery.getAuditStatus()),"audit_status",userHouseQuery.getAuditStatus()).
                eq(Objects.nonNull(userHouseQuery.getStatus()),"status",userHouseQuery.getStatus()).
                like(StringUtil.notEmpty(userHouseQuery.getProjectId()),"project_id",userHouseQuery.getProjectId()).
                between(StringUtil.notEmpty(userHouseQuery.getMovieHouseTime()) && StringUtil.notEmpty(userHouseQuery.getMovieHouseTime1()),
                "movie_house_time",
                userHouseQuery.getMovieHouseTime(),
                userHouseQuery.getMovieHouseTime1())
                .between(StringUtil.notEmpty(userHouseQuery.getLeaveTime()) && StringUtil.notEmpty(userHouseQuery.getLeaveTime1()),
                "leave_time",
                userHouseQuery.getLeaveTime(),
                userHouseQuery.getLeaveTime1())
                .orderBy("create_time",false);
        Page<JazUserHouseDO> jazUserAunts =  selectPage(page,wrapper);

        //查询项目类型
        List<String> projectIds = jazUserAunts.getRecords().stream().filter(a ->Objects.nonNull(a.getProjectId()))
                .map(JazUserHouseDO::getProjectId).distinct().collect(Collectors.toList());
        if(ObjectUtils.isEmpty(projectIds)){
            return jazUserAunts;
        }
        List<String> projectIds1 = new ArrayList<>();
        for (int i = 0; i < projectIds.size(); i++) {
            projectIds1.addAll(Arrays.asList(projectIds.get(i).split(",")));
        }
        List<JazSysProjectDO>  jazSysProjectDOS = jazSysProjectService.selectList(new EntityWrapper<JazSysProjectDO>().in("id",projectIds1));
        jazUserAunts.getRecords().forEach(a-> {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 定义日期格式
            a.setProjectName(jazSysProjectDOS.stream().filter(b -> Objects.nonNull(a.getProjectId())).
                    filter(b -> a.getProjectId().contains(b.getId().toString())).
                    map(JazSysProjectDO::getName).collect(Collectors.joining(",")));
            //新增代码
            if(a.getLeaveTime()!=null){
                // 首先，我们将 Date 转换为 LocalDateTime。
                LocalDateTime localDateTime1 = a.getLeaveTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                LocalDateTime localDateTime2 = a.getMovieHouseTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                // 然后我们计算两个 LocalDateTime 之间的 Duration。
                Duration duration = Duration.between(localDateTime1, localDateTime2);
                // 我们从 Duration 中获取总小时数。
                long totalHours = Math.abs(duration.toHours());
                // 计算天数，确保只有当小时数等于或超过24时才增加天数。
                long stayDays = (totalHours + 23) / 24;
                a.setStayDays(stayDays);
            }
            a.setMovieHouseTime1(dateFormat.format(a.getMovieHouseTime()));
//            JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(a.getBedNumberId());
//            if (jazBedNumberDO!=null){
//                a.setBedCode(jazBedNumberDO.getCode());
//                JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO.getHouseTypeId());
//                a.setCommunityName(jazHouseTypesDO.getName());
//                a.setBuildNumber(jazHouseTypesDO.getBuildNumber());
//            }
        });

        return jazUserAunts;
    }

    /**
     * 新增住宿
     *
     * @param userHouseDO
     * @return
     */
    @Override
    public Result<String> insertUserHouse(JazUserHouseDO userHouseDO) throws ParseException {
        if (userHouseDO==null){
            return Result.fail();
        }
        // 获取用户信息
        UserDO userDO = userDao.selectById(userHouseDO.getSysUserid());
        if (userDO!=null){
            // 获取手机号码
            userHouseDO.setPhone(userDO.getMobile());
            userHouseDO.setUsername(userDO.getName());
        }
        // 获取项目类型
        Wrapper<JazUserAuntDO> wrapper = new EntityWrapper<JazUserAuntDO>().eq("sys_userid", userHouseDO.getSysUserid());
        JazUserAuntDO jazUserAuntDO = jazUserAuntService.selectOne(wrapper);
        if (jazUserAuntDO!=null) {
            userHouseDO.setProjectId(jazUserAuntDO.getProjectId());
            if (StringUtil.notEmpty(userHouseDO.getProjectId())) {
                String[] projects = userHouseDO.getProjectId().split(",");
                List<JazSysProjectDO> jazSysProjectDOS = jazSysProjectService.selectList(new EntityWrapper<JazSysProjectDO>().in("id", projects));
                userHouseDO.setProjectName(jazSysProjectDOS.stream().map(JazSysProjectDO::getName).collect(Collectors.joining(",")));

            }
        }
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        userHouseDO.setAuditStatus(1);
        userHouseDO.setAuditResult(3);


        userHouseDO.setMovieHouseTime(formatter.parse(userHouseDO.getMovieHouseTime1()));
        if (!StringUtils.isEmpty(userHouseDO.getLeaveTime1())){
            userHouseDO.setLeaveTime(formatter.parse(userHouseDO.getLeaveTime1()));
        }
        if (formatter.parse(userHouseDO.getMovieHouseTime1()).before(new Date())){
            userHouseDO.setStatus(1);
        }else {
            userHouseDO.setStatus(0);
        }
        JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(userHouseDO.getBedNumberId());
        jazBedNumberDO.setIsOccupied(0);
        jazBedNumberService.updateById(jazBedNumberDO);
        JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO.getHouseTypeId());
        userHouseDO.setBedCode(jazBedNumberDO.getCode());
        userHouseDO.setBuildNumber(jazHouseTypesDO.getBuildNumber());
        userHouseDO.setLat(jazHouseTypesDO.getLat());
        userHouseDO.setLon(jazHouseTypesDO.getLon());
        userHouseDO.setCommunityName(jazHouseTypesDO.getName());
        List<JazBedNumberDO> list1 = jazBedNumberService.selectList(new EntityWrapper<JazBedNumberDO>().eq("house_type_id", jazHouseTypesDO.getId()));
        List<JazBedNumberDO> collect = list1.stream().filter(e -> e.getIsOccupied().equals(0)).collect(Collectors.toList());
        jazHouseTypesDO.setStay(collect.size());
        if (Objects.equals(jazHouseTypesDO.getCanStay(), collect.size())) {
            jazHouseTypesDO.setStatus(2);
        } else if (collect.isEmpty()) {
            jazHouseTypesDO.setStatus(0);
        } else if (jazHouseTypesDO.getCanStay() >collect.size()) {
            jazHouseTypesDO.setStatus(1);
        }
        jazHouseTypesService.updateById(jazHouseTypesDO);

        //--------------------------
        Integer insert = this.baseMapper.insert(userHouseDO);
        // 通过
        if (insert > 0) {
            // 如果插入成功，获取新插入记录的ID
            Long newId = userHouseDO.getId(); // 假设ID是Long类型
            // 现在newId包含了新插入记录的ID
            JazMessageDO jazMessageDO1 = new JazMessageDO();
            jazMessageDO1.setMessageType(1);
            jazMessageDO1.setSenderId(ShiroUtils.getUserId());
            jazMessageDO1.setReceiverId(userHouseDO.getSysUserid());
            jazMessageDO1.setMessageContent(MessagesEnum.MESSAGE_105.getMsg());
            jazMessageDO1.setMessageNum(MessagesEnum.MESSAGE_105.getNum());
            jazMessageDO1.setUserHouseId(newId); // 此处使用了刚插入记录的ID
            jazMessageDO1.setIsRead(0);
            jazMessageDO1.setHasSendSms(true);
            jazMessageService.senMessage(jazMessageDO1);
        }

        return insert==0?Result.fail():Result.ok();
    }

    /**
     * 根据id删除用户信息
     *
     * @param id
     * @return
     */
    @Override
    public Result<Object> deletedById(Long id) {
        if (id==null){
            return Result.fail();
        }
        JazUserHouseDO jazUserHouseDO = this.selectById(id);
        if (jazUserHouseDO.getAuditResult().equals(1)||jazUserHouseDO.getAuditResult().equals(2)||
                jazUserHouseDO.getAuditStatus().equals(0)||jazUserHouseDO.getStatus().equals(2)){
            boolean b = this.deleteById(id);
            return b?Result.ok():Result.fail();
        } else  {
              return Result.fail("阿姨已入住，无法进行删除！");
        }

    }

    /**
     * 根据id查询住宿详情
     *
     * @param id
     * @return
     */
    @Override
    public JazUserHouseDO getUserHouseById(Long id) throws ParseException {
        if (id == null){
            return null;
        }
        JazUserHouseDO jazUserHouseDO = this.selectById(id);
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        jazUserHouseDO.setMovieHouseTime1(formatter.format(jazUserHouseDO.getMovieHouseTime()));
        if (jazUserHouseDO.getLeaveTime()!=null){
            jazUserHouseDO.setLeaveTime1(formatter.format(jazUserHouseDO.getLeaveTime()));
        }
        // 查询项目类型
        if (StringUtil.notEmpty(jazUserHouseDO.getProjectId())){
            String[] projects = jazUserHouseDO.getProjectId().split(",");
            List<JazSysProjectDO>  jazSysProjectDOS = jazSysProjectService.selectList(new EntityWrapper<JazSysProjectDO>().in("id",projects));
            jazUserHouseDO.setProjectName(jazSysProjectDOS.stream().map(JazSysProjectDO::getName).collect(Collectors.joining(",")));
        }
        return jazUserHouseDO;
    }

    /**
     * 修改住宿审核信息
     *
     * @param jazUserHouseDO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result updateExamineHouse(JazUserHouseDO jazUserHouseDO) {
        JazUserHouseDO userHouseDO = this.selectById(jazUserHouseDO.getId());
        if (userHouseDO == null){
            return  Result.fail();
        }
        // 判断审核结果是不是通过
        if (jazUserHouseDO.getAuditResult()==0){
            userHouseDO.setAuditStatus(1);
            userHouseDO.setAuditResult(0);
        } else if (jazUserHouseDO.getAuditResult()==1) {
            userHouseDO.setAuditStatus(1);
            userHouseDO.setAuditResult(1);
            if (StringUtil.notEmpty(jazUserHouseDO.getRefuseReason())){
                userHouseDO.setRefuseReason(jazUserHouseDO.getRefuseReason());
            }else {
                return Result.fail("请输入拒绝原因");
            }
        }
        boolean update = this.updateById(userHouseDO);
        // 发送审核消息
        if (userHouseDO.getAuditResult()==0){
            // 通过
            JazMessageDO jazMessageDO1 = new JazMessageDO();
            jazMessageDO1.setMessageType(1);
            jazMessageDO1.setSenderId(ShiroUtils.getUserId());
            jazMessageDO1.setReceiverId(userHouseDO.getSysUserid());
            jazMessageDO1.setMessageContent(MessagesEnum.MESSAGE_105.getMsg());
            jazMessageDO1.setMessageNum(MessagesEnum.MESSAGE_105.getNum());
//            jazMessageDO1.setObjectId(userHouseDO.getId());
            jazMessageDO1.setIsRead(0);
            jazMessageDO1.setHasSendSms(true);
            jazMessageService.senMessage(jazMessageDO1);
        } else if (userHouseDO.getAuditResult()==1) {
            // 拒绝
            JazMessageDO jazMessageDO1 = new JazMessageDO();
            jazMessageDO1.setMessageType(1);
            jazMessageDO1.setSenderId(ShiroUtils.getUserId());
            jazMessageDO1.setReceiverId(userHouseDO.getSysUserid());
            jazMessageDO1.setHasSendSms(true);
            jazMessageDO1.setMessageContent(MessagesEnum.MESSAGE_106.getMsg()+userHouseDO.getRefuseReason());
            jazMessageDO1.setMessageNum(MessagesEnum.MESSAGE_106.getNum());
//            jazMessageDO1.setObjectId(userHouseDO.getId());
            jazMessageDO1.setIsRead(0);
            jazMessageService.senMessage(jazMessageDO1);
        }
        return update?Result.ok():Result.fail();
    }

    /**
     * 修改住宿信息
     *
     * @param jazUserHouseDO
     * @return
     */
    @Override
    public Result updateHouse(JazUserHouseDO jazUserHouseDO) throws ParseException {
        if (jazUserHouseDO == null){
            return Result.fail();
        }
        JazUserHouseDO jazUserHouseDO1 = this.selectById(jazUserHouseDO.getId());

        // 判断审核结果是不是通过
        if (jazUserHouseDO.getAuditResult()==0||jazUserHouseDO.getAuditResult()==3){
            jazUserHouseDO.setAuditStatus(1);
            jazUserHouseDO.setAuditResult(3);
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date parse = formatter.parse(jazUserHouseDO.getMovieHouseTime1());

            jazUserHouseDO.setMovieHouseTime(parse);
            if (!StringUtils.isEmpty(jazUserHouseDO.getLeaveTime1())){
                jazUserHouseDO.setLeaveTime(formatter.parse(jazUserHouseDO.getLeaveTime1()));
            }

            if (jazUserHouseDO.getLeaveTime()!=null) {
                // 解析用户离开时间
                if (jazUserHouseDO.getLeaveTime().before(new Date())) {
                    jazUserHouseDO.setStatus(2);  // 更改状态为已离开
                    JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(jazUserHouseDO.getBedNumberId());
                    jazBedNumberDO.setIsOccupied(1);
                    jazBedNumberService.updateById(jazBedNumberDO);
                    JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO.getHouseTypeId());
                    jazHouseTypesDO.setStay(jazHouseTypesDO.getStay()-1);
                    updateHouseBedType(jazHouseTypesDO);
                }else {
                    if (parse.before(new Date())){
                        jazUserHouseDO.setStatus(1);
                    }else {
                        jazUserHouseDO.setStatus(0);
                    }
                }
            }else {
                if (parse.before(new Date())){
                    jazUserHouseDO.setStatus(1);
                }else {
                    jazUserHouseDO.setStatus(0);
                }
            }

            //发送短信

            //如果床号id不变，不释放床号或者给分配床号
            if (jazUserHouseDO1.getBedNumberId()==null) {

                JazBedNumberDO jazBedNumberDO1 = jazBedNumberService.selectById(jazUserHouseDO.getBedNumberId());

                JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO1.getHouseTypeId());

//                if (StringUtil.notEmpty(jazUserHouseDO1.getMovieHouseTime())){
//                    Date date = dateFormat.parse(jazUserHouseDO1.getMovieHouseTime());
//                    if ((date.compareTo(new Date()) < 0)){
//                        jazUserHouseDO.setStatus(0);
//                    }else {
//                        jazUserHouseDO.setStatus(1);
//                    }
//                }

//                jazUserHouseDO1.setAuditStatus(1);
//                jazUserHouseDO1.setAuditResult(3);
                JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(jazUserHouseDO.getBedNumberId());
                jazBedNumberDO.setIsOccupied(0);
                jazBedNumberService.updateById(jazBedNumberDO);
                jazUserHouseDO.setBuildNumber(jazBedNumberDO1.getCode());
                jazUserHouseDO.setBedCode(jazBedNumberDO1.getCode());
                jazUserHouseDO.setBuildNumber(jazHouseTypesDO.getBuildNumber());
                jazUserHouseDO.setLat(jazHouseTypesDO.getLat());
                jazUserHouseDO.setLon(jazHouseTypesDO.getLon());
                jazUserHouseDO.setCommunityName(jazHouseTypesDO.getName());
                List<JazBedNumberDO> list1 = jazBedNumberService.selectList(new EntityWrapper<JazBedNumberDO>().eq("house_type_id", jazHouseTypesDO.getId()));
                List<JazBedNumberDO> collect = list1.stream().filter(e -> e.getIsOccupied().equals(0)).collect(Collectors.toList());
                jazHouseTypesDO.setStay(collect.size());
                updateHouseBedType(jazHouseTypesDO);

            }else if (!jazUserHouseDO.getBedNumberId().equals(jazUserHouseDO1.getBedNumberId())){
                //释放床号
                JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(jazUserHouseDO1.getBedNumberId());
                jazBedNumberDO.setIsOccupied(1);
                jazBedNumberService.updateById(jazBedNumberDO);

                //占有新床号
                JazBedNumberDO jazBedNumberDO1 = jazBedNumberService.selectById(jazUserHouseDO.getBedNumberId());
                jazBedNumberDO1.setIsOccupied(0);
                jazBedNumberService.updateById(jazBedNumberDO1);

                JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO1.getHouseTypeId());
                jazUserHouseDO.setBedCode(jazBedNumberDO1.getCode());
                jazUserHouseDO.setBuildNumber(jazHouseTypesDO.getBuildNumber());
                jazUserHouseDO.setLat(jazHouseTypesDO.getLat());
                jazUserHouseDO.setLon(jazHouseTypesDO.getLon());
//                jazUserHouseDO1.setAuditStatus(1);
//                jazUserHouseDO1.setAuditResult(3);
                jazUserHouseDO.setCommunityName(jazHouseTypesDO.getName());
                List<JazBedNumberDO> list1 = jazBedNumberService.selectList(new EntityWrapper<JazBedNumberDO>().eq("house_type_id", jazHouseTypesDO.getId()));
                List<JazBedNumberDO> collect = list1.stream().filter(e -> e.getIsOccupied().equals(0)).collect(Collectors.toList());
                jazHouseTypesDO.setStay(collect.size());
                updateHouseBedType(jazHouseTypesDO);

            }

        } else if (jazUserHouseDO.getAuditResult()==1) {
            jazUserHouseDO.setAuditStatus(1);
            jazUserHouseDO.setAuditResult(1);
            jazUserHouseDO.setRefuseReason(jazUserHouseDO.getRefuseReason());
        }

        // 发送审核消息
        if (jazUserHouseDO.getAuditResult()==0||jazUserHouseDO.getAuditResult()==3){
            // 通过
            JazMessageDO jazMessageDO1 = new JazMessageDO();
            jazMessageDO1.setMessageType(1);
            jazMessageDO1.setSenderId(ShiroUtils.getUserId());
            jazMessageDO1.setReceiverId(jazUserHouseDO1.getSysUserid());
            jazMessageDO1.setMessageContent(MessagesEnum.MESSAGE_105.getMsg());
            jazMessageDO1.setMessageNum(MessagesEnum.MESSAGE_105.getNum());
            jazMessageDO1.setUserHouseId(jazUserHouseDO.getId());
            jazMessageDO1.setIsRead(0);
            jazMessageDO1.setHasSendSms(true);
            jazMessageService.senMessage(jazMessageDO1);
        } else if (jazUserHouseDO.getAuditResult()==1) {
            // 拒绝
            JazMessageDO jazMessageDO1 = new JazMessageDO();
            jazMessageDO1.setMessageType(1);
            jazMessageDO1.setSenderId(ShiroUtils.getUserId());
            jazMessageDO1.setReceiverId(jazUserHouseDO1.getSysUserid());
//            jazMessageDO1.setHasSendSms(true);
            jazMessageDO1.setMessageContent(MessagesEnum.MESSAGE_106.getMsg()+jazUserHouseDO.getRefuseReason());
            jazMessageDO1.setMessageNum(MessagesEnum.MESSAGE_106.getNum());
//            jazMessageDO1.setObjectId(userHouseDO.getId());
            jazMessageDO1.setIsRead(0);
            jazMessageService.senMessage(jazMessageDO1);
        }
        boolean update = this.updateById(jazUserHouseDO);
        return update?Result.ok():Result.fail();
    }

    private void updateHouseBedType(JazHouseTypesDO jazHouseTypesDO) {
        if (Objects.equals(jazHouseTypesDO.getCanStay(), jazHouseTypesDO.getStay())){
            jazHouseTypesDO.setStatus(2);
        }else if (jazHouseTypesDO.getStay()==null|| jazHouseTypesDO.getStay()==0){
            jazHouseTypesDO.setStatus(0);
        }else if (jazHouseTypesDO.getCanStay()>jazHouseTypesDO.getStay()){
            jazHouseTypesDO.setStatus(1);
        }
        jazHouseTypesService.updateById(jazHouseTypesDO);
    }

    /**
     * 阿姨端 预约入住
     * @param userHouseDO
     * @return
     */
    @Override
    public Result<?> auntSubscribeHouse(JazUserHouseDO userHouseDO) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //参数校验
        Assert.notNull(userHouseDO,"参数异常");
        Assert.notNull(userHouseDO.getUsername(),"请输入姓名");
        Assert.notNull(userHouseDO.getSex(),"请选择性别");
        Assert.notNull(userHouseDO.getPhone(),"请输入联系方式");
//        Assert.notNull(userHouseDO.getMovieHouseTime(),"请选择入住时间");
        //入住时间要大于当前时间
//        String movieHouseTim = sf.format(userHouseDO.getMovieHouseTime());
        Long userId = JWTUtil.getUser().getId();
        userHouseDO.setSysUserid(userId);
        Wrapper<JazUserAuntDO> wrapper = new EntityWrapper<JazUserAuntDO>().eq("sys_userid",userId);
        JazUserAuntDO jazUserAuntDO = jazUserAuntService.selectOne(wrapper);
        if (jazUserAuntDO!=null) {
            userHouseDO.setProjectId(jazUserAuntDO.getProjectId());
            if (StringUtil.notEmpty(userHouseDO.getProjectId())) {
                String[] projects = userHouseDO.getProjectId().split(",");
                List<JazSysProjectDO> jazSysProjectDOS = jazSysProjectService.selectList(new EntityWrapper<JazSysProjectDO>().in("id", projects));
                userHouseDO.setProjectName(jazSysProjectDOS.stream().map(JazSysProjectDO::getName).collect(Collectors.joining(",")));

            }
        }
        userHouseDO.setAuditStatus(0);
        userHouseDO.setMovieHouseTime(parseToDate(userHouseDO.getMovieHouseTime1()));
//        if (new Date().compareTo(userHouseDO.getMovieHouseTime()) > 0) {
//            return Result.fail("入住时间不得小于当前时间");
//        }
        userHouseDO.setStatus(0);
        userHouseDO.setAuditResult(2);
        Integer insertOrUpdate = 0;
        if (userHouseDO.getId()!=null&&!userHouseDO.getId().equals("")){ //有id说明有记录了进行修改
            insertOrUpdate = this.baseMapper.updateById(userHouseDO);
        }else { //没有id说明没有记录进行新增
            insertOrUpdate = this.baseMapper.insert(userHouseDO);
        }
        return insertOrUpdate==0?Result.fail():Result.ok();
    }

    /**
     * 阿姨预约入住详情
     * @return
     */
    @Override
    public JazUserHouseDO auntGetHouse() {
        JazUserHouseDO jazUserHouseDO = new JazUserHouseDO();
        Long userId = JWTUtil.getUser().getId();
        //查询用户最新的一条入住信息
        List<JazUserHouseDO> jazUserHouseDOS = this.selectList(new EntityWrapper<JazUserHouseDO>().eq("sys_userid", userId).orderBy("create_time", false));
        if(null!=jazUserHouseDOS && !jazUserHouseDOS.isEmpty()){
            jazUserHouseDO = jazUserHouseDOS.get(0);
        }


        return jazUserHouseDO;
    }


    public static Date parseToDate(String dateTimeStr) {
        // 定义输入的日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");

        // 解析字符串为 LocalDateTime
        LocalDateTime localDateTime = LocalDateTime.parse(dateTimeStr, formatter);

        // 将 LocalDateTime 转换为 Date 对象，秒和毫秒默认为 0
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

        return date;
    }



    @Autowired
    private ApplicationContext applicationContext;

    @Transactional
    @Override
    public void updateHouseStatus() {
        SecurityManager securityManager = applicationContext.getBean(SecurityManager.class);
        SecurityUtils.setSecurityManager(securityManager);

        try {
            Subject subject = SecurityUtils.getSubject();
            if (subject.isAuthenticated()) {
                Session session = subject.getSession(false);
                if (session != null) {
                    session.stop();
                }
            }
            System.out.println("1小时执行一次这个定时任务");

            int batchSize = 100;  // 每批处理的数量，可以根据实际情况调整
            int offset = 0;

            while (true) {
                EntityWrapper<JazUserHouseDO> wrapper = new EntityWrapper<>();
                // 分批查询
                wrapper.last("LIMIT " + offset + ", " + batchSize);
                List<JazUserHouseDO> userHouseList = this.selectList(wrapper);

                if (userHouseList.isEmpty()) {
                    break;  // 如果没有更多数据，退出循环
                }

                List<JazUserHouseDO> userHouseToUpdate = new ArrayList<>();
                List<JazBedNumberDO> bedNumbersToUpdate = new ArrayList<>();
                Map<Long, JazHouseTypesDO> houseTypesMap = new HashMap<>();

                for (JazUserHouseDO userHouse : userHouseList) {
                    if (userHouse.getLeaveTime() != null && userHouse.getLeaveTime().before(new Date())) {
                        userHouse.setStatus(2);
                        updateRelatedEntities(userHouse, userHouseToUpdate, bedNumbersToUpdate, houseTypesMap);
                    } else {
                        boolean movieTimePassed = userHouse.getMovieHouseTime() != null && userHouse.getMovieHouseTime().before(new Date());
                        userHouse.setStatus(movieTimePassed ? 1 : 0);
                        userHouseToUpdate.add(userHouse);
                    }
                }

                // 执行批量更新
                if (!userHouseToUpdate.isEmpty()) {
                    this.updateBatchById(userHouseToUpdate);
                    log.info("批量更改住宿状态");
                }

                if (!bedNumbersToUpdate.isEmpty()) {
                    jazBedNumberService.updateBatchById(bedNumbersToUpdate);
                    log.info("批量更改床号状态");
                }

                if (!houseTypesMap.isEmpty()) {
                    for (JazHouseTypesDO houseType : houseTypesMap.values()) {
                        jazHouseTypesService.updateById(houseType);
                    }
                    log.info("批量更改房型已住数量");
                }

                // 清理已处理的数据
                userHouseToUpdate.clear();
                bedNumbersToUpdate.clear();
                houseTypesMap.clear();

                offset += batchSize;  // 移动偏移量到下一个批次
            }
        } catch (Exception e) {
            log.error("定时任务处理时发生错误", e);
        } finally {
            ThreadContext.unbindSubject();
        }
    }

    private void updateRelatedEntities(JazUserHouseDO userHouse, List<JazUserHouseDO> userHouseToUpdate,
                                       List<JazBedNumberDO> bedNumbersToUpdate, Map<Long, JazHouseTypesDO> houseTypesMap) {
        JazBedNumberDO bedNumber = jazBedNumberService.selectById(userHouse.getBedNumberId());
        if (bedNumber != null) {
            bedNumber.setIsOccupied(1); // 设为1，表示床位未被占用
            bedNumbersToUpdate.add(bedNumber);

            Long houseTypeId = bedNumber.getHouseTypeId();
            JazHouseTypesDO houseType = houseTypesMap.get(houseTypeId);
            if (houseType == null) {
                houseType = jazHouseTypesService.selectById(houseTypeId);
                houseTypesMap.put(houseTypeId, houseType);
            }

            if (houseType != null) {
                // 查询当前房型所有床位状态
                List<JazBedNumberDO> allBeds = jazBedNumberService.selectList(
                        new EntityWrapper<JazBedNumberDO>().eq("house_type_id", houseType.getId())
                );

                // 计算已住的床位数量 (IsOccupied == 0)
                int stay = (int) allBeds.stream()
                        .filter(bn -> bn.getIsOccupied().equals(0)) // 0 表示已住
                        .count();

                houseType.setStay(stay);

                if (stay >= houseType.getCanStay()) {
                    houseType.setStatus(2); // 房型已满
                } else if (stay == 0) {
                    houseType.setStatus(0); // 没有已住的床位
                } else {
                    houseType.setStatus(1); // 部分床位已住
                }
            }
        }

        userHouseToUpdate.add(userHouse);
    }











    //    @Transactional
//    @Override
    public void updateHouseStatus1() {
        // 从Spring上下文中获取SecurityManager Bean
        SecurityManager securityManager = applicationContext.getBean(SecurityManager.class);

        // 将SecurityManager绑定到当前线程
        SecurityUtils.setSecurityManager(securityManager);

        try {
            // 获取Subject，现在可以执行Shiro相关的操作了
            Subject subject = SecurityUtils.getSubject();
            if (subject.isAuthenticated()) {
                Session session = subject.getSession(false);
                if (session != null) {
                    session.stop();
                }
            }

            // 查询所有需要更新状态的订单
            EntityWrapper<JazUserHouseDO> wrapper = new EntityWrapper<>();
            System.out.println("3小时执行一次这个定时任务");


            List<JazUserHouseDO> userHouseList = this.selectList(wrapper);
            List<JazUserHouseDO> userHouseToUpdate = new ArrayList<>();
            List<JazBedNumberDO> bedNumbersToUpdate = new ArrayList<>();
            List<JazHouseTypesDO> houseTypesToUpdate = new ArrayList<>();
            for (JazUserHouseDO userHouse : userHouseList) {

                if (userHouse.getLeaveTime() != null && userHouse.getLeaveTime().before(new Date())) {
                    // 解析用户离开时间

                        userHouse.setStatus(2);  // 更改状态为已离开
                        userHouseToUpdate.add(userHouse);


                        JazBedNumberDO jazBedNumberDO = jazBedNumberService.selectById(userHouse.getBedNumberId());
                        if (jazBedNumberDO != null) {
                            jazBedNumberDO.setIsOccupied(1);  // 释放床号
                            bedNumbersToUpdate.add(jazBedNumberDO);

                            JazHouseTypesDO jazHouseTypesDO = jazHouseTypesService.selectById(jazBedNumberDO.getHouseTypeId());
                            if (jazHouseTypesDO != null) {
                                List<JazBedNumberDO> list1 = jazBedNumberService.selectList(
                                        new EntityWrapper<JazBedNumberDO>().eq("house_type_id", jazHouseTypesDO.getId())
                                );

                                long availableBedsCount = list1.stream().filter(bed -> bed.getIsOccupied().equals(0)).count();
                                jazHouseTypesDO.setStay((int) availableBedsCount);

                                if (Objects.equals(jazHouseTypesDO.getCanStay(), jazHouseTypesDO.getStay())) {
                                    jazHouseTypesDO.setStatus(2);
                                } else if (jazHouseTypesDO.getStay() == 0) {
                                    jazHouseTypesDO.setStatus(0);
                                } else if (jazHouseTypesDO.getCanStay() > jazHouseTypesDO.getStay()) {
                                    jazHouseTypesDO.setStatus(1);
                                }
                                houseTypesToUpdate.add(jazHouseTypesDO);
                            }
                        }
                    } else {
                    boolean movieTimePassed = userHouse.getMovieHouseTime() != null && userHouse.getMovieHouseTime().before(new Date());
                    userHouse.setStatus(movieTimePassed ? 1 : 0);
                    userHouseToUpdate.add(userHouse);
                }
            }

            // 批量更新
            if (!userHouseToUpdate.isEmpty()) {
                this.updateBatchById(userHouseToUpdate);
                System.out.println("批量更改住宿状态");
            }

            if (!bedNumbersToUpdate.isEmpty()) {
                jazBedNumberService.updateBatchById(bedNumbersToUpdate);
                System.out.println("批量更改床号状态");
            }

            if (!houseTypesToUpdate.isEmpty()) {
                jazHouseTypesService.updateBatchById(houseTypesToUpdate);
                System.out.println("批量更改房型已住数量");
            }

        } finally {
            // 清理线程状态
            ThreadContext.unbindSubject();
//            ThreadContext.remove();
        }
    }

}
